Next | Prev | Up | Top | Contents | Index

Waiting for Block I/O to Complete

The pfxstrategy() routine initiates the I/O operation to fill a buffer based on a buf_t structure. Then it has to wait for the I/O to complete. The functions for managing this synchronization are summarized in Table 9-22.

Functions for Synchronizing Block I/O
Function NameHeader FilesCan Sleep?Purpose
biodone(D3) ddi.hNRelease buffer after I/O and wake up waiting process.
bioerror(D3) ddi.hNManipulate error fields in a buf_t.
biowait(D3) ddi.hYSuspend process pending completion of I/O.
geterror(D3) ddi.hNRetrieve error number from a buf_t.
physiock(D3) ddi.hYValidate a raw I/O request and pass to a strategy function.
uiophysio(D3)ddi.hYValidate a raw I/O request and pass to a strategy function.
undma(D3) ddi.h?Unlock physical memory after I/O complete
userdma(D3) ddi.h?Lock physical memory in user space.small number of


How the strategy() Entry Point Is Called

The pfxstrategy() entry point is called directly from the filesystem or virtual memory management, or it can be called indirectly from a pfxread() or pfxwrite() entry point (see "Calling Entry Point strategy() From Entry Point read() or write()").


Strategies of the strategy() Entry Point

Typically the pfxstrategy() routine must interact with its interrupt handler. The pfxstrategy() routine can be designed in either of two ways, synchronous or asynchronous.

The synchronous pfxstrategy() routine initiates every I/O operation. Its interrupt handler is responsible only for detecting and signalling the completion of one I/O. The pfxstrategy() routine proceeds as follows:

  1. Lock the data buffer in memory using userdma().

  2. Place the address of the buf_t where the pfxintr() entry point can find it.

  3. Program the device (see "Setting Up a DMA Transfer") and initiate the I/O activity.

  4. Call biowait().
When the interrupt handler is entered, the handler uses bioerror() if necessary, and biodone() to signal the completion of the I/O. Then it exits. The strategy code, which is waiting in the call to biowait(), regains control following the call to biodone(), and can use geterror() to check the results.

The asynchronous pfxstrategy() routine only initiates the first I/O operation of a series, and never waits. It proceeds as follows:

  1. Lock the data buffer in memory using userdma().

  2. Append the address of the buf_t to a queue shared with the interrupt handler.

  3. If the queue was empty, no I/O is in progress. Call a subroutine that programs the device and initiates the I/O.

  4. Return to the caller. The caller (a filesystem or paging system or uiophysio()) waits using biowait().
When the interrupt occurs, the handler proceeds as follows:

  1. The first queued buf_t has completed. Remove it from the queue.

  2. Apply bioerror() if necessary, and biodone() to the buf_t. This releases the caller of the strategy routine from biowait().

  3. If any operations remain in the queue, call a subroutine to program and initiate the next one.

Next | Prev | Up | Top | Contents | Index